﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace Kugar.Core.BaseStruct
{
    /// <summary>
    ///     扩展了System.Threading.Timer类;<br/>
    ///     增加：<br/>
    ///     1.IsStopWhenRun属性，用于设定，当在定时器回调函数时，定时器是否停止计时（防止重入现象）。省去每次要用Timer的时候，都要在回调的时候去处理定时器的暂停<br/>
    ///     2.Start，Stop函数，用于启动或者关闭定时器。调用Stop函数后，不会打断正在调用的处理函数<br/>
    ///     3.IsRunning属性，用于判断定时器是否已经启动
    /// </summary>
    public class TimerEx:IDisposable
    {
        private Timer baseTimer = null;
        private bool isStopWhenRun = true;
        private TimerCallback _callback = null;
        private object lockerObj=new object();
        private int runInterval = 0;
        private bool isDisponsed = false;
        private bool isStop = false;
        
        public TimerEx(TimerCallback callback, int interval,object state)
        {
            _callback = callback;
            runInterval = interval;
            baseTimer = new Timer(timerCallback, state, interval, 0);
        }

        public bool IsStopWhenRun
        {
            set { isStopWhenRun = value; }
            get { return isStopWhenRun; }
        }

        public void Start()
        {
            lock (lockerObj)
            {
                isStop = false;
                baseTimer.Change(runInterval, 0);
            }
        }

        public void Stop()
        {
            lock (lockerObj)
            {
                isStop = true;
                baseTimer.Change(Timeout.Infinite, Timeout.Infinite);
            }
        }

        public bool IsRunning { get { return !isStop; } }

        private void timerCallback(object state)
        {
            bool s;

            lock (lockerObj)
            {
                s = this.isStopWhenRun;
            }

            if (s)
            {
                baseTimer.Change(Timeout.Infinite, Timeout.Infinite);
            }

            try
            {
                _callback(state);
            }
            catch (Exception)
            {
                
            }


            if (s && !isStop)
            {
                baseTimer.Change(this.runInterval, 0);
            }
        }

        public void Dispose()
        {
            lock (lockerObj)
            {
                if (!isDisponsed)
                {
                    isStop = true;
                    baseTimer.Change(Timeout.Infinite, Timeout.Infinite);
                    baseTimer.Dispose();
                    _callback = null;

                    isDisponsed = true;

                    GC.SuppressFinalize(this);
                }
            }

        }

        ~TimerEx()
        {
            Dispose();
        }
    }
}
